#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "nyu.h"

long nyu_print(long argc, long *argv)
{
    long i;

    for (i = 1; i < argc; i++) {
        long v = argv[i];

        switch (v & 0x3) {
        case 0:
            /* 数値 */
            printf("%ld", v >> 2);
            break;

        case 1:
            /* ネイティブ関数 */
            printf("Native(%p)", ((void *)(v ^ 0x1)));
            break;

        case 2:
            /* オブジェクト */
            {
                NyuObject *obj = NYU_OBJECT(v ^ 0x2);
                NyuString *str = nyu_object_to_string(obj);
                printf("%s", str->str);
            }
            break;

        case 3:
            /* ブロック */
            printf("Block(%p)", ((void *)(v ^ 0x3)));
            break;
        }
    }

    return 0;
}

long nyu_println(long argc, long *argv)
{
    nyu_print(argc, argv);
    printf("\n");

    return 0;
}

int main(int argc, char *argv[])
{
    int i, ret;

    if (argc < 2) {
        fprintf(stderr, "usage: %s file [args]\n", argv[0]);
        return -1;
    }

    yyin = fopen(argv[1], "r");
    if (!yyin) {
        perror(argv[1]);
        return -1;
    }

    nyu_initialize();

    input_filename = argv[1];

    current_scope = nyu_scope_new(NULL);
    current_scope->argc =
        (NYU_MAX_ARGLEN < argc - 1 ? NYU_MAX_ARGLEN : argc - 1);

    /* プログラム名 */
    {
        //char *prog_name = strdup(argv[1]);
        NyuString *prog_name = nyu_string_new(argv[1]);
        current_scope->argv[0] = ((long)prog_name | 0x2);
    }

    /* 引数を入れる */
    for (i = 2; i < argc && i < NYU_MAX_ARGLEN + 1; i++) {
        /* とりあえず数値で始まる引数はlongにする…… */
        if (isdigit(argv[i][0])) {
            current_scope->argv[i - 1] = strtol(argv[i], NULL, 0) << 2;
        } else {
            //char *str = strdup(argv[i]);
            NyuString *str = nyu_string_new(argv[i]);
            current_scope->argv[i - 1] = ((long)str | 0x2);
        }
    }

    nyu_add_func("print", nyu_print);
    nyu_add_func("println", nyu_println);

    ret = yyparse();

    fclose(yyin);
    yyin = NULL;

    nyu_finalize();

    return ret;
}
